/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.openide.awt;
import java.awt.*;
import java.awt.event.*;
import java.util.Iterator;
import java.util.Vector;
import java.util.EventObject;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import org.openide.*;
import org.openide.loaders.*;
import org.openide.cookies.InstanceCookie;
import org.openide.util.actions.Presenter;
/**
* Toolbar provides a component which is useful for displaying commonly used
* actions. It can be dragged inside its <code>ToolbarPanel</code> to
* customize its location.
*
* @version 1.0
* @author David Peroutka, Libor Kramolis
*/
/* * * * * * * * *
* class Toolbar *
* * * * * * * * */
public class Toolbar extends JToolBar implements MouseInputListener {
public static int BASIC_HEIGHT = 34;
static int HEIGHT_TOLERANCE = 5;
static int TOP = 0;
static int LEFT = 3;
static int BOTTOM = 0;
static int RIGHT = 3;
private boolean floatable;
private DnDListener listener;
private boolean dragging;
private Point startPoint;
static final long serialVersionUID =5011742660516204764L;
public Toolbar () {
this (""); // NOI18N
}
public Toolbar (String name) {
this (name, false);
}
/**
* Creates a new <code>Toolbar</code>.
* @param name a <code>String</code> containing the associated name
*/
public Toolbar (String name, boolean f) {
super();
setName (name);
setFloatable (false);
setBorder (new CompoundBorder (new EtchedBorder(),
new EmptyBorder (TOP, LEFT, BOTTOM, RIGHT)));
floatable = f;
dragging = false;
setLayout (new InnerLayout (2, 2));
addGrip();
}
public Component add (Component comp) {
add ("Action", comp); // NOI18N
return comp;
}
public void removeAll () {
super.removeAll();
addGrip();
}
/**
* When Toolbar is floatable, ToolbarGrid is added as Grid as first toolbar component
*/
void addGrip () {
if (floatable) {
ToolbarGrip grip = new ToolbarGrip();
grip.addMouseListener (this);
grip.addMouseMotionListener (this);
add ("Grip", grip); // NOI18N
}
}
static public int rowCount (int height) {
int rows = 1;
int max_height = (BASIC_HEIGHT + HEIGHT_TOLERANCE);
while (height > max_height) {
// 5 pixels is tolerance so toolbar can be high (BASIC_HEIGHT + HEIGHT_TOLERANCE)
// but it will be set to BASIC_HEIGHT high
rows++;
height -= max_height;
}
return rows;
}
public void setDnDListener (DnDListener l) {
listener = l;
}
protected void fireDragToolbar (int dx, int dy, int type) {
if (listener != null)
listener.dragToolbar (new DnDEvent (this, getName(), dx, dy, type));
}
protected void fireDropToolbar (int dx, int dy, int type) {
if (listener != null)
listener.dropToolbar (new DnDEvent (this, getName(), dx, dy, type));
}
// MouseInputListener
public void mouseClicked (MouseEvent e) {
}
public void mouseEntered (MouseEvent e) {
}
public void mouseExited (MouseEvent e) {
}
public void mousePressed (MouseEvent e) {
startPoint = new Point (e.getX(), e.getY());
}
public void mouseReleased (MouseEvent e) {
if (dragging) {
fireDropToolbar (e.getX() - startPoint.x,
e.getY() - startPoint.y,
DnDEvent.DND_ONE);
dragging = false;
}
}
public void mouseDragged (MouseEvent e) {
int m = e.getModifiers();
int type = DnDEvent.DND_ONE;
if (e.isControlDown())
type = DnDEvent.DND_LINE;
else if (((m & InputEvent.BUTTON2_MASK) != 0) || ((m & InputEvent.BUTTON3_MASK) != 0))
type = DnDEvent.DND_END;
if (startPoint == null)
startPoint = new Point (e.getX(), e.getY());
fireDragToolbar (e.getX() - startPoint.x,
(e.getY() - startPoint.y),
type);
dragging = true;
}
public void mouseMoved (MouseEvent e) {
}
/* * * * * * * * * * * *
* inner class Folder *
* * * * * * * * * * * */
/**
* This class can be used to produce a <code>Toolbar</code> instance from
* the given <code>DataFolder</code>.
*/
final static class Folder extends FolderInstance {
/** the <code>Toolbar</code> to work with */
private JToolBar toolbar;
/**
* Creates a new folder on the specified <code>DataFolder</code>.
* @param folder a <code>DataFolder</code> to work with
*/
public Folder (DataFolder folder) {
super (folder);
recreate ();
}
/**
* Returns a <code>Toolbar</code> representee of this folder.
* @return a <code>Toolbar</code> representee of this folder
*/
public final JToolBar getToolbar() {
if (toolbar == null) {
toolbar = new Toolbar (folder.getNodeDelegate ().getDisplayName (), true);
}
return toolbar;
}
/**
* Full name of the data folder's primary file separated by dots.
* @return the name
*/
public String instanceName () {
return getToolbar().getClass().getName();
}
/**
* Returns the root class of all objects.
* @return Object.class
*/
public Class instanceClass ()
throws java.io.IOException, ClassNotFoundException {
return getToolbar().getClass();
}
/** If no instance cookie, tries to create execution action on the
* data object.
*/
protected org.openide.cookies.InstanceCookie acceptDataObject (DataObject dob) {
InstanceCookie ic = super.acceptDataObject (dob);
if (
ic == null &&
!(dob instanceof DataFolder) &&
dob.getCookie (InstanceCookie.class) == null
) {
return new InstanceSupport.Instance (ExecBridge.createButton (dob));
} else {
return ic;
}
}
private static Class separatorClass = javax.swing.JToolBar.Separator.class;
/**
* Accepts only cookies that can provide <code>Toolbar</code>.
* @param cookie an <code>InstanceCookie</code> to test
* @return true if the cookie can provide accepted instances
*/
protected InstanceCookie acceptCookie (InstanceCookie cookie)
throws java.io.IOException, ClassNotFoundException {
Class c = cookie.instanceClass();
if (Toolbar.class.isAssignableFrom(c)) {
return cookie;
}
if (Presenter.Toolbar.class.isAssignableFrom(c)) {
return cookie;
}
if (separatorClass.isAssignableFrom(c)) {
return cookie;
}
return null;
}
/**
* Returns a <code>Toolbar.Folder</code> cookie for the specified
* <code>DataFolder</code>.
* @param df a <code>DataFolder</code> to create the cookie for
* @return a <code>Toolbar.Folder</code> for the specified folder
*/
protected org.openide.cookies.InstanceCookie acceptFolder(DataFolder df) {
return null; // PENDING new Toolbar.Folder(df);
}
/**
* Updates the <code>Toolbar</code> represented by this folder.
*
* @param cookies array of instance cookies for the folder
* @return the updated <code>ToolbarPool</code> representee
*/
protected Object createInstance(InstanceCookie[] cookies)
throws java.io.IOException, ClassNotFoundException {
// refresh the toolbar's content
getToolbar().removeAll();
for (int i = 0; i < cookies.length; i++) {
try {
Object obj = cookies[i].instanceCreate();
if (obj instanceof Presenter.Toolbar) {
obj = ((Presenter.Toolbar)obj).getToolbarPresenter();
}
if (obj instanceof Component) {
Component comp = (Component)obj;
getToolbar().add (comp);
}
} catch (java.io.IOException ex) {
} catch (ClassNotFoundException ex) {
}
}
// invalidate the toolbar and its parent
toolbar.invalidate ();
java.awt.Container parent = toolbar.getParent ();
if (parent != null) {
parent.validate();
parent.repaint();
}
return toolbar;
}
} // end of inner class Folder
/* * * * * * * * * * * * * *
* inner class ToolbarGrip *
* * * * * * * * * * * * * */
private class ToolbarGrip extends JPanel {
static final int HGAP = 1;
static final int VGAP = 1;
static final int STEP = 1;
static final int WIDTH = 2;
int columns;
Dimension dim;
static final long serialVersionUID =-8819972936203315276L;
public ToolbarGrip () {
this (2);
}
public ToolbarGrip (int col) {
super ();
columns = col;
int width = (col-1)*STEP + col*WIDTH + 2*HGAP;
dim = new Dimension (width, width);
setBorder (new EmptyBorder (VGAP, HGAP, VGAP, HGAP));
setToolTipText (Toolbar.this.getName());
}
public void paint (Graphics g) {
Dimension size = getSize();
int top = VGAP;
int bottom = size.height-1-VGAP;
int height = bottom - top;
g.setColor( getBackground() );
for (int i = 0, x = HGAP; i < columns; i++, x += WIDTH+STEP) {
g.draw3DRect (x, top, WIDTH, height, true);
}
}
public Dimension getMinimumSize () {
return dim;
}
public Dimension getPreferredSize () {
return getMinimumSize();
}
} // end of inner class ToolbarGrid
private class InnerLayout implements LayoutManager {
/** Grip component */
private Component grip;
/** Vector of Components
* @associates Component*/
private Vector actions;
/** horizontal gap */
private int hgap;
/** vertical gap */
private int vgap;
/**
* Constructs a new InnerLayout.
*/
public InnerLayout () {
this (5, 5);
}
/**
* Constructs a new InnerLayout with the specified gap values.
* @param hgap the horizontal gap variable
* @param vgap the vertical gap variable
*/
public InnerLayout (int hgap, int vgap) {
this.hgap = hgap;
this.vgap = vgap;
actions = new Vector();
}
/**
* Adds the specified component with the specified name to the layout.
*/
public void addLayoutComponent (String name, Component comp) {
synchronized (comp.getTreeLock()) {
if ("Grip".equals (name)) { // NOI18N
grip = comp;
} else
if ("Action".equals (name)) { // NOI18N
actions.addElement (comp);
} else
throw new IllegalArgumentException
("cannot add to layout: unknown constraint: " + name); // NOI18N
}
}
/**
* Adds the specified component to the layout, using the specified
* constraint object.
*/
public void addLayoutComponent (Component comp, Object constraints) {
throw new IllegalArgumentException();
}
/**
* Removes the specified component from the layout.
*/
public void removeLayoutComponent (Component comp) {
synchronized (comp.getTreeLock()) {
if (grip == comp)
grip = null;
else
actions.removeElement (comp);
}
}
/**
* Calculates the preferred size dimensions for the specified panal given
* the components in the specified parent container.
*/
public Dimension preferredLayoutSize (Container target) {
synchronized (target.getTreeLock()) {
Dimension dim = new Dimension (0, 0);
int size = actions.size();
if ((grip != null) && grip.isVisible()) {
Dimension d = grip.getPreferredSize();
dim.width += d.width;
dim.width += hgap;
}
for (int i = 0; i < size; i++) {
Component comp = (Component)actions.elementAt (i);
if (comp.isVisible()) {
Dimension d = comp.getPreferredSize();
dim.width += d.width;
dim.height = Math.max (dim.height, d.height);
dim.width += hgap;
}
}
Insets insets = target.getInsets();
dim.width += insets.left + insets.right;
dim.height += insets.top + insets.bottom;
return dim;
}
}
/**
* Calculates the minimum size dimensions for the specified panal given
* the components in the specified parent container.
*/
public Dimension minimumLayoutSize (Container target) {
return preferredLayoutSize (target);
}
/**
* Calculates the maximum size dimensions for the specified panal given
* the components in the specified parent container.
*/
public Dimension maximumLayoutSize (Container target) {
synchronized (target.getTreeLock()) {
Dimension dim = new Dimension (0, 0);
int size = actions.size();
if ((grip != null) && grip.isVisible()) {
Dimension d = grip.getPreferredSize();
dim.width += d.width;
dim.width += hgap;
}
Component last = null;
for (int i = 0; i < size; i++) {
Component comp = (Component)actions.elementAt (i);
if (comp.isVisible()) {
Dimension d = comp.getPreferredSize();
dim.width += d.width;
dim.height = Math.max (dim.height, d.height);
dim.width += hgap;
last = comp;
}
}
if (last != null) {
Dimension prefSize = last.getPreferredSize();
Dimension maxSize = last.getMaximumSize();
if (prefSize != maxSize) {
dim.width = dim.width - prefSize.width + maxSize.width;
dim.height = Math.max (dim.height, maxSize.height);
}
}
Insets insets = target.getInsets();
dim.width += insets.left + insets.right;
dim.height += insets.top + insets.bottom;
return dim;
}
}
/**
* Lays out the container in the specified panel.
*/
public void layoutContainer (Container target) {
synchronized (target.getTreeLock()) {
Insets insets = target.getInsets();
Dimension dim = target.getSize();
int fullHeight = dim.height;
int bottom = dim.height - insets.bottom - 1;
int top = 0 + insets.top;
int left = insets.left;
int maxPosition = dim.width - (insets.left + insets.right) - hgap;
int right = dim.width - insets.right;
maxPosition = right;
int height = bottom - top;
int size = actions.size();
int w, h;
if ((grip != null) && grip.isVisible()) {
Dimension d = grip.getPreferredSize();
grip.setBounds (left, top + vgap, d.width, bottom - top - 2*vgap);
left += d.width;
left += hgap;
}
for (int i = 0; i < size; i++) {
left += hgap;
Component comp = (Component)actions.elementAt (i);
Dimension d;
Dimension minSize = comp.getMinimumSize();
if (i == size - 1)
d = comp.getMaximumSize();
else
d = comp.getPreferredSize();
w = d.width;
h = Math.min (height, d.height);
if ((left < maxPosition) &&
(left + w > maxPosition)) {
if (maxPosition - left >= minSize.width)
w = maxPosition - left;
}
comp.setBounds (left, (fullHeight - d.height)/2, w, h);
// if (i == size - 1)
// d = comp.getMaximumSize();
// else
// d = comp.getPreferredSize();
// if ((left + d.width) > right)
// w = right - left;
// else
// w = d.width;
// h = Math.min (height, d.height);
// comp.setBounds (left, (fullHeight - d.height)/2, w, h);
left += d.width;
}
}
}
/**
* Returns the alignment along the x axis.
*/
public float getLayoutAlignmentX (Container target) {
return 0;
}
/**
* Returns the alignment along the y axis.
*/
public float getLayoutAlignmentY (Container target) {
return (float)0.5;
}
/**
* Invalidates the layout, indicating that if the layout manager has cached
* information it should ne discarded.
*/
public void invalidateLayout (Container target) {
// check target components with local vars (grip, actions)
}
} // end of class InnerLayout
public abstract interface DnDListener extends java.util.EventListener {
public void dragToolbar (DnDEvent e);
public void dropToolbar (DnDEvent e);
} // end of interface DnDListener
public static class DnDEvent extends EventObject {
public static final int DND_ONE = 1;
public static final int DND_END = 2;
public static final int DND_LINE = 3;
public String name;
public int dx;
public int dy;
public int type;
static final long serialVersionUID =4389530973297716699L;
public DnDEvent (Toolbar toolbar, String name, int dx, int dy, int type) {
super (toolbar);
this.name = name;
this.dx = dx;
this.dy = dy;
this.type = type;
}
} // end of class DnDEvent
} // end of class Toolbar
/*
* Log
* 37 dperoutka-src-gandalf1.36 1/20/00 Libor Kramolis
* 36 dperoutka-src-gandalf1.35 1/18/00 Libor Kramolis
* 35 dperoutka-src-gandalf1.34 1/13/00 Jaroslav Tulach File names can be
* localized.
* 34 dperoutka-src-gandalf1.33 1/12/00 Ian Formanek NOI18N
* 33 dperoutka-src-gandalf1.32 1/12/00 Ian Formanek NOI18N
* 32 dperoutka-src-gandalf1.31 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun
* Microsystems Copyright in File Comment
* 31 dperoutka-src-gandalf1.30 8/16/99 Ian Formanek Toolbars are smaller in
* height
* 30 dperoutka-src-gandalf1.29 8/9/99 Ian Formanek Generated Serial Version
* UID
* 29 dperoutka-src-gandalf1.28 8/1/99 Petr Hrebejk Toolbar.Grip apperance
* fixed
* 28 dperoutka-src-gandalf1.27 7/30/99 Libor Kramolis
* 27 dperoutka-src-gandalf1.26 6/25/99 Ian Formanek Fixed painting of toolbar
* grips
* 26 dperoutka-src-gandalf1.25 6/10/99 Michal Fadljevic SystemColor changed to
* UIManager.getColor(...)
* 25 dperoutka-src-gandalf1.24 6/10/99 Michal Fadljevic setForeground() in
* paint() added
* 24 dperoutka-src-gandalf1.23 6/10/99 Libor Kramolis
* 23 dperoutka-src-gandalf1.22 6/10/99 Libor Kramolis
* 22 dperoutka-src-gandalf1.21 6/9/99 Jaroslav Tulach Executables can be in
* menu & toolbars.
* 21 dperoutka-src-gandalf1.20 6/8/99 Ian Formanek ---- Package Change To
* org.openide ----
* 20 dperoutka-src-gandalf1.19 6/4/99 Ian Formanek Toolbar Grips made
* slighly more decent
* 19 dperoutka-src-gandalf1.18 6/4/99 Libor Kramolis
* 18 dperoutka-src-gandalf1.17 5/15/99 Libor Kramolis
* 17 dperoutka-src-gandalf1.16 5/13/99 Libor Kramolis
* 16 dperoutka-src-gandalf1.15 5/11/99 Jaroslav Tulach ToolbarPool changed to
* look better in Open API
* 15 dperoutka-src-gandalf1.14 5/7/99 Libor Kramolis
* 14 dperoutka-src-gandalf1.13 4/8/99 Libor Kramolis
* 13 dperoutka-src-gandalf1.12 4/7/99 Libor Kramolis
* 12 dperoutka-src-gandalf1.11 4/5/99 Ian Formanek
* 11 dperoutka-src-gandalf1.10 4/4/99 Ian Formanek Latest Libor's version
* 10 dperoutka-src-gandalf1.9 3/30/99 Ian Formanek FolderInstance creation
* in single thread
* 9 dperoutka-src-gandalf1.8 3/26/99 Libor Kramolis
* 8 dperoutka-src-gandalf1.7 3/24/99 Libor Kramolis
* 7 dperoutka-src-gandalf1.6 3/24/99 Libor Kramolis
* 6 dperoutka-src-gandalf1.5 3/24/99 Libor Kramolis
* 5 dperoutka-src-gandalf1.4 3/24/99 Libor Kramolis
* 4 dperoutka-src-gandalf1.3 3/24/99 Libor Kramolis
* 3 dperoutka-src-gandalf1.2 2/11/99 Jaroslav Tulach SystemAction is
* javax.swing.Action
* 2 dperoutka-src-gandalf1.1 1/25/99 David Peroutka
* 1 dperoutka-src-gandalf1.0 1/25/99 David Peroutka
* $
*/